﻿using System;
using System.Collections.Generic;
using System.Text;
using UPos.Core.DataDriver;
using UPos.Core.Entity;
using UPos.Core.LogProvider;
using UPos.Core.RecordProvider;

namespace UPos.Core.SaleProvider
{
    public class PosSales
    {
        #region SQLs

        #region SALES
        static string SALES =
@"select a.s# FID, a.ct BizDate, a.cr MachineNo, a.s# BillNumber, a.cr CreaterNumber, u.xm CreaterName, sum(b.sl) Amount, sum(b.cj) Paymentmoney
from pos_sydd a join pos_syds b on a.s# = b.d#
join sys_user_info u on a.cr = u.yx#
where Convert(varchar(10), ct, 120) = ?
[upedFidWhere]
group by a.s#, a.ct, a.cr, a.s#, a.cr, u.xm
order by a.s#";
        #endregion

        #region SALEITEMS
        static string SALEITEMS =
@"select d# FParentID, p# Number, sl Qty, cj TotalPrice from pos_syds where d# in (@parentids)
order by d#";
        #endregion

        #region RECEIVEITEMS
        static string RECEIVEITEMS = @"
select b# FParentID, je PayMoney, b_ TypeID from pos_sydb where b# in (@parentids)
order by b#";
        #endregion

        #endregion

        DbOdbc Odbc = new DbOdbc(); 
        
        public RecordSQLite Recorder { get; set; }

        public ShopInfo Shop { get; set; }

        string ShopFID { get { return Shop.ShopFID; } }

        public DateTime SaleDate { get; set; }

        public bool NeedUp { get { return GetAllCount() > Recorder.GetUpedCount(); } }

        public PosSales(DateTime date, ShopInfo shopInfo, RecordSQLite recorder)
        {
            SaleDate = date;

            Shop = shopInfo;

            Recorder = recorder;
            recorder.SaleDate = date;
            recorder.ShopFID = Shop.ShopFID;
        }

        public int GetAllCount()
        {
            var count = Odbc.ExecuteScalar(
                "select count(1) from pos_sydd where Convert(varchar(10), ct, 120) = ?",
                "saledate".ODP(SaleDate.ToString("yyyy-MM-dd")));

            LogSQLite.Write("PosSales.GetAllCount", "return({0})", count);

            return Convert.ToInt32(count);
        }

        public List<Sale> GetNeedUp()
        {
            try
            {
                return GetNeedUpUnSafe();
            }
            catch (Exception e)
            {
                LogSQLite.Write("PosSales.GetNeedUp.Exception", e.Message);
                return null;
            }
        }

        List<Sale> GetNeedUpUnSafe()
        {
            LogSQLite.Write("PosSales.GetNeedUp", "next(Recorder.GetUpedFid)");

            var upedFids = Recorder.GetUpedFid();
            var upedFidWhere = GenerateUpedFidWhere(upedFids);

            LogSQLite.Write("GenerateUpedFidWhere", "return(" + upedFidWhere + ") next(ExecuteReader const SALES)");

            string sql = SALES.Replace("[upedFidWhere]", upedFidWhere);
            StringBuilder builder = new StringBuilder("'");
            List<Sale> list = new List<Sale>();
            using (var reader = Odbc.ExecuteReader(sql, "saledate".ODP(SaleDate.ToString("yyyy-MM-dd"))))
            {
                LogSQLite.Write("ExecuteReader", "({0}) return ({1}) next(Builder List)", sql, reader.HasRows);

                if (!reader.HasRows)
                    return list;

                while (reader.Read())
                {
                    list.Add(new Sale(reader));
                    builder.Append(list[list.Count - 1].FID);
                    builder.Append("','");
                }
                if (builder.Length >= 4)
                    builder.Remove(builder.Length - 2, 2);
            }

            sql = SALEITEMS.Replace("@parentids", builder.ToString());
            using (var entriesReader = Odbc.ExecuteReader(sql))
            {
                LogSQLite.Write("ExecuteReader", "({0}) return ({1}) next(Builder List)", sql, entriesReader.HasRows);

                int index = 0;
                List<SaleEntry> entries = null;
                string parentid = null;
                while (entriesReader.Read())
                {
                    parentid = entriesReader.GetString(entriesReader.GetOrdinal("FParentID"));
                    if (entries == null || entries[0].FParentID != parentid)
                    {
                        entries = new List<SaleEntry>();
                        list[index].SaleItems = entries;
                        index++;
                    }
                    entries.Add(new SaleEntry(entriesReader));
                }
            }

            sql = RECEIVEITEMS.Replace("@parentids", builder.ToString());
            using (var entriesReader = Odbc.ExecuteReader(sql))
            {
                LogSQLite.Write("ExecuteReader", "({0}) return ({1}) next(Builder List)", sql, entriesReader.HasRows);

                int index = 0;
                List<ReceiveEntries> entries = null;
                string parentid = null;
                while (entriesReader.Read())
                {
                    parentid = entriesReader.GetString(entriesReader.GetOrdinal("FParentID"));
                    if (entries == null || entries[0].FParentID != parentid)
                    {
                        entries = new List<ReceiveEntries>();
                        list[index].ReceiveItems = entries;
                        index++;
                    }
                    entries.Add(new ReceiveEntries(entriesReader, r =>
                    {
                        switch (r.GetString(r.GetOrdinal("TypeID")))
                        {
                            case "1": return "CH"; //现金
                            case "4": return "CI"; //银联
                            default: return "OT";
                        }
                    }));
                }
            }

            LogSQLite.Write("PosSales.GetNeedUp", "return List({0})", list.Count);
            return list;
        }

        private string GenerateUpedFidWhere(List<string> upedFids)
        {
            var preWhere = string.Join("' and s# <> '", upedFids);
            if (string.IsNullOrWhiteSpace(preWhere))
                return string.Empty;
            else
                return " and s# <> '" + preWhere + "'";
        }
    }
}